package com.example.musicaiap.service

import android.Manifest
import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.annotation.OptIn
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.media3.common.AudioAttributes
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.session.CommandButton
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
import androidx.media3.session.SessionCommand
import androidx.media3.session.SessionResult
import com.example.musicaiap.R
import com.example.musicaiap.data.repository.FavoriteStateRepository
import com.example.musicaiap.data.repository.MusicRepository
import com.google.common.collect.ImmutableList
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
import android.util.Log

/**
 * 音乐播放服务，负责后台播放和通知栏控制
 */
@AndroidEntryPoint
@UnstableApi
@SuppressLint("UnsafeOptInUsageError")
class MusicService : MediaSessionService() {

    @Inject
    lateinit var musicRepository: MusicRepository

    @Inject
    lateinit var favoriteStateRepository: FavoriteStateRepository

    private lateinit var player: ExoPlayer
    private lateinit var mediaSession: MediaSession
    private lateinit var mediaSessionCallback: MediaSessionCallback

    // 创建服务作用域的协程
    private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

    companion object {
        private const val TAG = "MusicService"
        const val COMMAND_TOGGLE_FAVORITE = "toggle_favorite"
        const val COMMAND_SHOW_LYRICS = "show_lyrics"
        const val NOTIFICATION_ID = 12321
        const val CHANNEL_ID = "music_service_channel_id"

        // 控制命令
        const val ACTION_PLAY = "play"
        const val ACTION_PAUSE = "pause"
        const val ACTION_PLAY_PAUSE = "play_pause"
        const val ACTION_NEXT = "next"
        const val ACTION_PREVIOUS = "previous"


        const val CUSTOM_COMMAND_TOGGLE_LIKE_ON = "android.media3.session.LIKE_ON"
        const val CUSTOM_COMMAND_TOGGLE_LIKE_OFF = "android.media3.session.LIKE_OFF"
        const val CUSTOM_COMMAND_TOGGLE_LYRIC_ON = "android.media3.session.LYRIC_ON"
        const val CUSTOM_COMMAND_TOGGLE_LYRIC_OFF = "android.media3.session.LYRIC_OFF"
    }

    override fun onCreate() {
        super.onCreate()

        // 初始化播放器
        initializePlayer()

        // 创建MediaSessionCallback并保存引用
        mediaSessionCallback = MediaSessionCallback()

        // 创建媒体会话，使用已创建的callback
        mediaSession = MediaSession.Builder(this, player)
            .setCallback(mediaSessionCallback)
            .build()

        setMediaNotificationProvider(MediaNotificationProvider(this))
//        setListener(MediaSessionServiceListener())

        // 监听收藏状态变化
        observeFavoriteStateChanges()
    }

    /**
     * 监听收藏状态变化
     * 优化版本：简化监听逻辑，只需要监听收藏状态变化事件
     */
    private fun observeFavoriteStateChanges() {
        // 监听所有歌曲的收藏状态变化事件
        serviceScope.launch {
            favoriteStateRepository.favoriteChanges.collect { event ->
                Log.d(TAG, "收到收藏状态变化事件: songId=${event.songId}, isFavorite=${event.isFavorite}")

                // 更新当前播放的歌曲UI（如果是当前播放的歌曲）
                mediaSessionCallback.updateFavoriteStatus(event.songId, event.isFavorite)
            }
        }
    }

    @OptIn(UnstableApi::class) // MediaSessionService.Listener
    private inner class MediaSessionServiceListener : Listener {

        /**
         * This method is only required to be implemented on Android 12 or above when an attempt is made
         * by a media controller to resume playback when the {@link MediaSessionService} is in the
         * background.
         */
        override fun onForegroundServiceStartNotAllowedException() {
            if (
                Build.VERSION.SDK_INT >= 33 &&
                checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) !=
                PackageManager.PERMISSION_GRANTED
            ) {
                // Notification permission is required but not granted
                return
            }
            val notificationManagerCompat = NotificationManagerCompat.from(this@MusicService)
            ensureNotificationChannel(notificationManagerCompat)
            val builder =
                NotificationCompat.Builder(this@MusicService, CHANNEL_ID)
                    .setSmallIcon(R.drawable.media3_notification_small_icon)
                    .setContentTitle(getString(R.string.notification_content_title))
                    .setStyle(
                        NotificationCompat.BigTextStyle().bigText(getString(R.string.notification_content_text))
                    )
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                    .setAutoCancel(true)
                    .also { builder ->
//                        getBackStackedActivity()?.let { builder.setContentIntent(it) }
                    }
            notificationManagerCompat.notify(NOTIFICATION_ID, builder.build())
        }
    }

    private fun ensureNotificationChannel(notificationManagerCompat: NotificationManagerCompat) {
        if (
            Build.VERSION.SDK_INT < 26 ||
            notificationManagerCompat.getNotificationChannel(CHANNEL_ID) != null
        ) {
            return
        }

        val channel =
            NotificationChannel(
                CHANNEL_ID,
                getString(R.string.notification_channel_name),
                NotificationManager.IMPORTANCE_DEFAULT,
            )
        notificationManagerCompat.createNotificationChannel(channel)
    }

    override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? {
        return mediaSession
    }

    override fun onDestroy() {
        // 释放资源
        mediaSession.release()
        player.release()
        super.onDestroy()
    }

    /**
     * 初始化播放器
     */
    private fun initializePlayer() {
        // 创建音频属性
        val audioAttributes = AudioAttributes.Builder()
            .setUsage(C.USAGE_MEDIA)
            .setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
            .build()

        // 创建播放器
        player = ExoPlayer.Builder(this)
            .setAudioAttributes(audioAttributes, true)
            .setHandleAudioBecomingNoisy(true)
            .build()
    }


private inner class MediaSessionCallback : MediaSession.Callback {
        var liked = false  // 将属性修改为公开，以便MusicService可以访问
        private var lyric = false
        private val customLayoutCommandButtons: List<CommandButton> =
            listOf(
                CommandButton.Builder()
                    .setDisplayName("已收藏")
                    .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_LIKE_ON, Bundle.EMPTY))
                    .setIconResId(R.drawable.player_ico_notify_player_liked)
                    .build(),
                CommandButton.Builder()
                    .setDisplayName("收藏")
                    .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_LIKE_OFF, Bundle.EMPTY))
                    .setIconResId(R.drawable.player_ico_notify_player_like)
                    .build(),
                CommandButton.Builder()
                    .setDisplayName("桌面歌词打开")
                    .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_LYRIC_ON, Bundle.EMPTY))
                    .setIconResId(R.drawable.player_ico_notify_player_lyric_open)
                    .build(),
                CommandButton.Builder()
                    .setDisplayName("桌面歌词关闭")
                    .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_LYRIC_OFF, Bundle.EMPTY))
                    .setIconResId(R.drawable.player_ico_notify_player_lyric)
                    .build(),
            )

        init {
            // 监听播放器当前媒体项变化，更新收藏状态
            player.addListener(object : Player.Listener {
                override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
                    mediaItem?.let { item ->
                        // 设置当前歌曲ID
                        favoriteStateRepository.setCurrentSong(item.mediaId)

                        // 加载并设置收藏状态
                        serviceScope.launch {
                            try {
                                val isFavorite = withContext(Dispatchers.IO) {
                                    musicRepository.isSongFavorite(item.mediaId)
                                }

                                // 同步到Repository，这将自动触发UI更新
                                favoriteStateRepository.initSongFavoriteState(item.mediaId, isFavorite)

                                // 同时也直接更新通知UI
                                updateFavoriteStatus(item.mediaId, isFavorite)
                            } catch (e: Exception) {
                                Log.e(TAG, "加载收藏状态失败: ${e.message}")
                            }
                        }
                    }
                }
            })

            // 初始检查当前歌曲的收藏状态
            player.currentMediaItem?.let { mediaItem ->
                favoriteStateRepository.setCurrentSong(mediaItem.mediaId)
                serviceScope.launch {
                    try {
                        val isFavorite = withContext(Dispatchers.IO) {
                            musicRepository.isSongFavorite(mediaItem.mediaId)
                        }
                        // 同步到Repository
                        favoriteStateRepository.initSongFavoriteState(mediaItem.mediaId, isFavorite)

                        // 直接更新UI
                        updateFavoriteStatus(mediaItem.mediaId, isFavorite)
                    } catch (e: Exception) {
                        Log.e(TAG, "初始化收藏状态失败: ${e.message}")
                    }
                }
            }
        }

        /**
         * 更新收藏状态
         * 优化版本：直接使用FavoriteStateRepository的状态
         * @param songId 歌曲ID
         * @param isFavorite 是否收藏
         */
        fun updateFavoriteStatus(songId: String, isFavorite: Boolean) {
            Log.d(TAG, "更新收藏状态: songId=$songId, isFavorite=$isFavorite")

            // 获取当前播放的歌曲ID
            val currentMediaItem = player.currentMediaItem ?: return
            val currentSongId = currentMediaItem.mediaId

            // 只有当songId与当前播放的歌曲ID匹配时才更新
            if (currentSongId == songId) {
                liked = isFavorite

                // 更新所有控制器的UI
                updateAllControllersLayout()
            }
        }

        /**
         * 更新收藏状态
         * 兼容旧方法，通过查询数据库获取收藏状态
         */
        fun updateFavoriteStatus(songId: String) {
            serviceScope.launch {
                val isFavorite = withContext(Dispatchers.IO) {
                    musicRepository.isSongFavorite(songId)
                }
                updateFavoriteStatus(songId, isFavorite)
            }
        }

        /**
         * 更新所有连接控制器的自定义布局
         * 确保所有控制器显示相同的状态
         */
        private fun updateAllControllersLayout() {
            mediaSession.connectedControllers.forEach { controller ->
                if (mediaSession.isMediaNotificationController(controller) ||
                    mediaSession.isAutomotiveController(controller) ||
                    mediaSession.isAutoCompanionController(controller)) {
                    val likeButton = customLayoutCommandButtons[if (liked) 0 else 1]
                    val lyricButton = customLayoutCommandButtons[if (lyric) 2 else 3]
                    mediaSession.setCustomLayout(
                        controller,
                        ImmutableList.of(likeButton, lyricButton)
                    )
                }
            }
        }

        // MediaSession.ConnectionResult.DEFAULT_SESSION_AND_LIBRARY_COMMANDS
        private val mediaNotificationSessionCommands =
            MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
                .also { builder ->
                    // Put all custom session commands in the list that may be used by the notification.
                    customLayoutCommandButtons.forEach { commandButton ->
                        commandButton.sessionCommand?.let { builder.add(it) }
                    }
                }
                .build()

        // ConnectionResult.DEFAULT_SESSION_AND_LIBRARY_COMMANDS
        // ConnectionResult.AcceptedResultBuilder
        override fun onConnect(
            session: MediaSession,
            controller: MediaSession.ControllerInfo
        ): MediaSession.ConnectionResult {
            if (
                session.isMediaNotificationController(controller) ||
                session.isAutomotiveController(controller) ||
                session.isAutoCompanionController(controller)
            ) {
                // 确保当前歌曲的收藏状态是最新的
                player.currentMediaItem?.let { mediaItem ->
                    serviceScope.launch {
                        val isFavorite = withContext(Dispatchers.IO) {
                            musicRepository.isSongFavorite(mediaItem.mediaId)
                        }
                        // 更新内部状态
                        liked = isFavorite

                        // 同步到Repository
                        favoriteStateRepository.initSongFavoriteState(mediaItem.mediaId, isFavorite)

                        // 更新UI
                        updateAllControllersLayout()
                    }
                }

                // 初始响应仍然使用当前状态
                val likeButton = customLayoutCommandButtons[if (liked) 0 else 1]
                val lyricButton = customLayoutCommandButtons[if (lyric) 2 else 3]
                return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
                    .setAvailableSessionCommands(mediaNotificationSessionCommands)
                    .setCustomLayout(ImmutableList.of(likeButton, lyricButton))
                    .build()
            }
            // Default commands without custom layout for common controllers.
            return MediaSession.ConnectionResult.AcceptedResultBuilder(session).build()
        }

        // MediaSession.isMediaNotificationController
        override fun onCustomCommand(
            session: MediaSession,
            controller: MediaSession.ControllerInfo,
            customCommand: SessionCommand,
            args: Bundle
        ): ListenableFuture<SessionResult> {
            if (customCommand.customAction !in arrayOf(
                    CUSTOM_COMMAND_TOGGLE_LIKE_ON,
                    CUSTOM_COMMAND_TOGGLE_LIKE_OFF,
                    CUSTOM_COMMAND_TOGGLE_LYRIC_ON,
                    CUSTOM_COMMAND_TOGGLE_LYRIC_OFF,
                )
            ) {
                return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
            }

            when (customCommand.customAction) {
                CUSTOM_COMMAND_TOGGLE_LIKE_ON, CUSTOM_COMMAND_TOGGLE_LIKE_OFF -> {
                    // 获取当前正在播放的歌曲ID
                    val currentMediaItem = player.currentMediaItem
                    val currentSongId = currentMediaItem?.mediaId

                    if (currentSongId != null) {
                        // 在协程中执行收藏操作
                        serviceScope.launch {
                            try {
                                // 获取当前状态
                                val currentState = favoriteStateRepository.getSongFavoriteState(currentSongId)

                                // 立即更新状态，提供即时反馈
                                val newState = !currentState
                                favoriteStateRepository.setSongFavoriteState(currentSongId, newState)

                                // 在后台执行实际的数据库操作
                                val actualState = withContext(Dispatchers.IO) {
                                    musicRepository.toggleFavorite(currentSongId)
                                }

                                // 确保最终状态与数据库一致
                                if (actualState != newState) {
                                    favoriteStateRepository.setSongFavoriteState(currentSongId, actualState)
                                }

                                Log.d(TAG, "切换收藏状态: $currentSongId, 新状态=$actualState")
                            } catch (e: Exception) {
                                Log.e(TAG, "切换收藏状态失败: ${e.message}")
                                // 恢复到原始状态
                                val actualState = withContext(Dispatchers.IO) {
                                    musicRepository.isSongFavorite(currentSongId)
                                }
                                favoriteStateRepository.setSongFavoriteState(currentSongId, actualState)
                            }
                        }
                    } else {
                        // 如果没有正在播放的歌曲，不改变状态，只显示一个短暂的消息
                        Toast.makeText(this@MusicService, "当前没有播放歌曲", Toast.LENGTH_SHORT).show()
                    }
                }
                CUSTOM_COMMAND_TOGGLE_LYRIC_ON -> lyric = false
                CUSTOM_COMMAND_TOGGLE_LYRIC_OFF -> lyric = true
            }

            // 如果是歌词按钮，立即更新UI
            if (customCommand.customAction == CUSTOM_COMMAND_TOGGLE_LYRIC_ON ||
                customCommand.customAction == CUSTOM_COMMAND_TOGGLE_LYRIC_OFF) {
                updateAllControllersLayout()
            }

            return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
        }
    }
}